#pragma once

#include "vec2.h"

OPEN_JLIB_NS


struct alignas(16) Box2 {

  Vec2 min, max;

  inline Box2 () noexcept = default;
  inline Box2 (f32 minx, f32 miny, f32 maxx, f32 maxy) : min(minx, miny), max(maxx, maxy) {
  }
  inline Box2 (Vec2 min, Vec2 max) : min(min), max(max) {
  }
  inline Box2 (const f32* m) noexcept : min(m), max(m+2) {
  }


  inline Box2& operator&= (Box2 v) noexcept {
    min = Vec2::max(min, v.min);
    max = Vec2::min(max, v.max);
    return *this;
  }
  inline Box2& operator|= (Box2 v) noexcept {
    min = Vec2::min(min, v.min);
    max = Vec2::max(max, v.max);
    return *this;
  }


  inline Box2 operator& (Box2 v) const noexcept {
    return {
      Vec2::max(min, v.min),
      Vec2::min(max, v.max),
    };
  }
  inline Box2 operator| (Box2 v) const noexcept {
    return {
      Vec2::min(min, v.min),
      Vec2::max(max, v.max),
    };
  }


  inline Vec2 operator~ () const noexcept {
    return max - min;
  }


  inline f32 x () const noexcept {
    return min.x();
  }
  inline f32 y () const noexcept {
    return min.y();
  }
  inline f32 X () const noexcept {
    return max.x();
  }
  inline f32 Y () const noexcept {
    return max.y();
  }


  inline Vec2 xy () const noexcept {
    return min;
  }
  inline Vec2 xY () const noexcept {
    return {min.p[0], max.p[1]};
  }
  inline Vec2 Xy () const noexcept {
    return {max.p[0], min.p[1]};
  }
  inline Vec2 XY () const noexcept {
    return max;
  }


  inline bool contains (Vec2 v) const noexcept {
    return v.p[0] >= min.p[0]
    && v.p[0] <= max.p[0]
    && v.p[1] >= min.p[1]
    && v.p[1] <= max.p[1];
  }
  inline bool contains (Box2 v) const noexcept {
    return v.min.p[0] >= min.p[0]
    && v.min.p[1] >= min.p[1]
    && v.max.p[0] <= max.p[0]
    && v.max.p[1] <= max.p[1];
  }
  inline bool intersect (Box2 v) const noexcept {
    return v.min.p[0] < max.p[0]
    && v.min.p[1] < max.p[1]
    && v.max.p[0] > min.p[0]
    && v.max.p[1] > min.p[1];
  }
};


CLOSE_JLIB_NS